import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'
import { Step, AuditConfig, Acquirer } from '@shared/interfaces/acquirer'
import { DataService } from '@shared/services/data.service'
import { User } from '@shared/interfaces/user'
import { DetailTabClass } from '@shared/classes/DetailTabClass'
import { PageService } from '@shared/services/page.service'
import { ActivatedRoute } from '@angular/router'
import { IBaseInfoColumn } from '@shared/interfaces/baseInfo'
import { CommonAcquirerService } from '@shared/services/acquirer.service'
import { Observable, of } from 'rxjs'
import { ISearchOption } from '@shared/interfaces/search'
import { mergeMap, concatMap, map, switchMap, tap } from 'rxjs/operators'
import { UserService } from 'app/routes/user/user.service'
import { NzMessageService } from 'ng-zorro-antd'
import { I18NService } from '@core'

enum EAuditType {
  exchangeRate = 'AUDIT.TYPE.EXCHANGERATE',
  riskControl = 'AUDIT.TYPE.RISKCONTROL',
  store = 'AUDIT.TYPE.STORE',
  transRefund = 'AUDIT.TYPE.TRANSREFUND',
  operation = 'AUDIT.TYPE.OPERATION',
}

@Component({
  selector: 'app-user-audit',
  templateUrl: './user-audit.component.html',
})
export class UserAuditComponent extends DetailTabClass<User> implements OnInit {
  @ViewChild('operate') operate: TemplateRef<void>
  @ViewChild('auditSelect') auditSelect: TemplateRef<void>

  Object = Object
  user: User
  fields = {}
  operateColumn: IBaseInfoColumn

  loading = false
  operationOptions$: Observable<Step[]>
  optionsMap: { [key: string]: Observable<Step[]> } = {}
  valuesMap: { [key: string]: number[] } = {}

  constructor(
    public pageService: PageService,
    public route: ActivatedRoute,
    private dataService: DataService,
    private commonAcquirerService: CommonAcquirerService,
    private userService: UserService,
    private msg: NzMessageService,
    private i18n: I18NService,
  ) {
    super(pageService, route)
  }

  ngOnInit() {
    this.user = this.dataService.user
    this.initOperateColumn()
    this.initialColumns()
  }

  initialColumns() {
    const { insCode } = this.user
    this.getFullAcquirer(insCode).subscribe(
      acquirer => {
        const { auditConfigs = [] } = acquirer.institution.common
        auditConfigs.forEach((config, index) => {
          const { type } = config
          if (!type) return
          this.initOptions(type)
          this.initFields(type, index)
          this.initIsEdits(type)
          this.initColumns(config)
          this.initSelectValues(type)
        })
        this.setupIdForColumn(this.fields)
      }
    )
  }

  initSelectValues(type: string): void {
    const auditConfigs = this.user.auditConfigs || []
    const existedConfig = auditConfigs.find(c => c.type === type)
    const steps = existedConfig ? existedConfig.steps : []
    this.valuesMap[type] = steps.map(step => step.stepID)
  }

  setupIdForColumn(keys: { [key: string]: string }) {
    for (const key of Object.keys(keys)) {
      for (const columns of this.columns[key]) {
        columns.filter(column => !column.operate).map((column, index) => (column.id = index))
      }
    }
  }

  initOptions(type: string): void {
    this.optionsMap[type] = this.requestAcquirerAudit(type).pipe(
      switchMap(config => of(config.steps))
    )
  }

  requestAcquirerAudit(type: string): Observable<AuditConfig> {
    const { insCode } = this.user
    return this.getFullAcquirer(insCode).pipe(
      switchMap(acquirer => of(acquirer.institution.common.auditConfigs.find(config => config.type === type)))
    )
  }

  getFullAcquirer(insCode: string): Observable<Acquirer> {
    return this.commonAcquirerService.getFullAcquirerByInsCode(insCode)
  }

  initOperateColumn(): void {
    this.operateColumn = {
      span: 4,
      label: 'GENERAL.INFO.OPERATION',
      labelI18n: 'GENERAL.INFO.OPERATION',
      operate: true,
      template: this.operate,
    }
  }

  initFields(type: string, index: number): void {
    this.fields[type] = (++index).toString()
  }

  initIsEdits(type: string): void {
    this.setEdit(type, 1)
  }

  initColumns(config: AuditConfig): void {
    const { type } = config
    const auditConfigs = this.user.auditConfigs || []
    const existedConfig = auditConfigs.find(c => c.type === type)
    const steps = existedConfig ? existedConfig.steps : []
    const auditColumns: IBaseInfoColumn[] = [
      {
        span: 20,
        label: type,
        labelI18n: EAuditType[type],
        value: this.getValue(steps),
        template: this.auditSelect,
      },
      this.operateColumn,
    ]
    this.columns[type] = []
    this.columns[type].push(auditColumns)
  }

  onSubmit(): void {
    const { username } = this.user
    const user = new User()
    Object.assign(user, this.user)
    user.auditPermissions = this.getAllAuditSteps()
    this.userService.update(username, user).subscribe(
      (updatedUser) => {
        this.msg.success('更新成功')
        this.user  = updatedUser
        this.dataService.setUser(this.user)
        this.initialColumns()
      },
      err => {
        const { error } = err
        this.msg.error(`更新失败: ${error.msg}`)
      }
    )
  }

  onCancel(): void {

  }

  getAllAuditSteps(): number[] {
    return Object.values(this.valuesMap).reduce((old, arr) => old.concat(arr))
  }

  private getValue(steps: Step[]): string {
    return steps.length === 0 ? this.trans('GENERAL.INFO.NONE') : steps.map(step => step.stepName).join(',')
  }

  private trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }

}
